#ifndef TRACKERRUNNER_HPP
#define TRACKERRUNNER_HPP

#include <cv.h>
#include "HandInterface.hpp"

#include <boost/thread.hpp>

class AbstractTrackerRunner {
public:
	virtual void init();
	virtual void run()=0;
	virtual void stop()=0;
	virtual ~AbstractTrackerRunner() {};
protected:
	cv::Ptr< cv::VideoCapture > capPtr;
	cv::Mat frame;
	cv::Mat prevFrame;
	virtual void setNextFrame();
	
	cv::Mat nextFrame;
	virtual void presetNextFrame();
	virtual void loadNextFrame();
};

class SingleTrackerRunner : public AbstractTrackerRunner {
public:
	explicit SingleTrackerRunner( cv::Ptr< AbstractTrackDataServer > trackDataServerPtr );
	virtual void run();
	virtual void stop();
	virtual ~SingleTrackerRunner();
protected:
	cv::Ptr< AbstractTrackDataServer > trackDataServerPtr;
	cv::Ptr< AbstractHandTracker > ht;
	cv::Ptr< HandLocaliser > hl;
	cv::Ptr< AbstractGestureClassifier > gc;
	
	cv::Rect trackingRect;
	cv::Rect trackingRectBuffer;
	bool isHandActive;
	bool isHandActiveBuffer;
	
	bool running;
	
	int localise();
	
	void runTracker();
	void runClassifier();
	
	boost::barrier nextFrameReadyBar;
	boost::barrier computationCompleteBar;
};

class FaceTracker;

class SingleTrackerFaceActivationRunner : public AbstractTrackerRunner {
public:
	explicit SingleTrackerFaceActivationRunner( cv::Ptr< AbstractTrackDataServer > trackDataServerPtr );
	virtual void run();
	virtual void stop();
	virtual ~SingleTrackerFaceActivationRunner();
protected:
	cv::Ptr< AbstractTrackDataServer > trackDataServerPtr;
	cv::Ptr< AbstractHandTracker > ht;
	cv::Ptr< HandLocaliser > hl;
	cv::Ptr< AbstractGestureClassifier > gc;
	
	cv::Rect trackingRect;
	cv::Rect trackingRectBuffer;
	bool isHandActive;
	bool isHandActiveBuffer;
	
	bool running;
	
	cv::Rect faceTrackingRect;
	cv::Rect faceTrackingRectBuffer;
	cv::Ptr< FaceTracker > ft;
	
	bool runningFaceTracker;
	
	int localise();
	
	void runTracker();
	void runClassifier();
	void runFaceTracker();
	
	hi::Barrier nextFrameReadyBar;
	hi::Barrier computationCompleteBar;
};

class DoubleTrackerRunner : public AbstractTrackerRunner {
public:
	explicit DoubleTrackerRunner( cv::Ptr< AbstractTrackDataServer > trackDataServerPtr );
	virtual void run();
	virtual void stop();
	virtual ~DoubleTrackerRunner();
protected:
	cv::Ptr< AbstractTrackDataServer > trackDataServerPtr;
	cv::Ptr< AbstractHandTracker > ht;
	cv::Ptr< HandLocaliser > hl;
	cv::Ptr< AbstractGestureClassifier > gc;
	
	cv::Rect trackingRect;
	cv::Rect trackingRectBuffer;
	bool isHandActive;
	bool isHandActiveBuffer;
	
	bool running;
	
	cv::Rect faceTrackingRect;
	cv::Rect faceTrackingRectBuffer;
	cv::Ptr< FaceTracker > ft;
	
	bool runningFaceTracker;
	
	cv::Ptr< AbstractHandTracker > ht2;
	cv::Ptr< AbstractGestureClassifier > gc2;
	
	cv::Rect secondaryTrackingRect;
	cv::Rect secondaryTrackingRectBuffer;
	bool isSecondaryActive;
	bool isSecondaryActiveBuffer;
	
	cv::Rect primaryInSecondaryIntersectionRect;
	
	int localise();
	
	void runTracker();
	void runClassifier();
	void runFaceTracker();
	
	void runSecondaryTracker();
	void runSecondaryClassifier();
	
	hi::Barrier nextFrameReadyBar;
	hi::Barrier computationCompleteBar;	
};

#endif